/*
 * @version: 1.0
 * @Author: zhl
 * @Date: 2021-09-06 14:58:00
 * @LastEditors: zhl
 * @LastEditTime: 2021-09-30 17:07:54
 * @Description: 该类用于封装698帧
 */

#include "MessagePacket.h"
#include "common.h"
#include "CLogger.h"
#include "hex.h"
#include "check_code.h"


#define MAX_REQUEST_OAD_NUM  200
#define PACKET_MAX_SIZE 8192
#define APDU_MAX_SIZE   8000



MessagePacket::MessagePacket(DLT698_FRAME &c_dlt698_frame){
}

MessagePacket::MessagePacket(){

}

MessagePacket::~MessagePacket(){
   
}
//
void  MessagePacket::set_lead_code(uint8_t *lc){
    if(NULL == lc){
        c_is_lead_code = false;
    }else{
        memcpy(c_dlt698_frame.lc, lc, sizeof(c_dlt698_frame.lc));
        c_is_lead_code = true;
    }
}

void  MessagePacket::set_scrambling_code(uint8_t sbc){
    c_dlt698_frame.sbc = sbc;
}

void  MessagePacket::set_control_code(uint8_t c){
    c_dlt698_frame.c.value = c;
}

int MessagePacket::set_slave_addr(std::string slave_addr){
    if(slave_addr.empty()){
        return 0;
    }
    int offset = 0;
    int sa_l = 16;
    unsigned char s_a[sa_l] = {0};
    str_to_hex((const char *)slave_addr.c_str(), s_a, &sa_l);
    c_dlt698_frame.sa_fc.sa_fc.addr_len = sa_l - 1;
    for(int j = --sa_l; j >=0; j--){
        memcpy(c_dlt698_frame.sa+offset, s_a+j, 1);
        offset += 1;
    }
    return offset;
}

void MessagePacket::init(){
    //前导码
    memset(c_dlt698_frame.lc, 0xFE, sizeof(c_dlt698_frame.lc));
    //扰码
    c_dlt698_frame.sbc = 0x33;
    //帧起始码
    c_dlt698_frame.sc = 0x68;
    //除起始字符、结束字符外的长度
    c_dlt698_frame.l = 0;
    //控制码
    c_dlt698_frame.c.value = 0x43;
    //地址域SA的第一个字节特征码
    c_dlt698_frame.sa_fc.sa_fc.la = 0x00;
    c_dlt698_frame.sa_fc.sa_fc.addr_type = 0x00;
    c_dlt698_frame.sa_fc.sa_fc.addr_len = 0x05;
    //地址域SA
    memset(c_dlt698_frame.sa, 0, sizeof(c_dlt698_frame.sa));
    //地址域CA
    c_dlt698_frame.ca = 0x00;
    //帧头校验码
    c_dlt698_frame.hcs = 0x00;
    //用户数据
    c_dlt698_frame.apdu = NULL;
    //帧校验码
    c_dlt698_frame.fcs = 0x00;
    //帧结束符
    c_dlt698_frame.em = 0x16;
}
//封装698协议帧
int  MessagePacket::packet_frame(uint8_t *buf, int buf_len, uint8_t *frame, int frame_len){

    if((NULL == buf) || (1 > buf_len) || (NULL == frame) || (buf_len > frame_len)){
        return -1;
    }
    int offset = 0;
    int cs_start = 0;
    int hcs_offset = 0;
    //前导码
    if(c_is_lead_code){
        memcpy(frame, c_dlt698_frame.lc, sizeof(c_dlt698_frame.lc));
        offset += sizeof(c_dlt698_frame.lc);
        cs_start += sizeof(c_dlt698_frame.lc);
    }
    //起始码
    memcpy(frame+offset, &(c_dlt698_frame.sc), sizeof(c_dlt698_frame.sc));
    offset += sizeof(c_dlt698_frame.sc);
    cs_start += sizeof(c_dlt698_frame.sc);
    //长度
    offset += sizeof(c_dlt698_frame.l);
    //控制域
    memcpy(frame+offset, &c_dlt698_frame.c.value, sizeof(c_dlt698_frame.c.value));
    offset += sizeof(c_dlt698_frame.c.value);
    //地址域
    memcpy(frame+offset, &c_dlt698_frame.sa_fc.value, sizeof(c_dlt698_frame.sa_fc.value));
    offset += sizeof(c_dlt698_frame.sa_fc.value);
    memcpy(frame+offset, c_dlt698_frame.sa, c_dlt698_frame.sa_fc.sa_fc.addr_len+1);
    offset += c_dlt698_frame.sa_fc.sa_fc.addr_len+1;
    //客户机地址ca
    memcpy(frame+offset, &c_dlt698_frame.ca, sizeof(c_dlt698_frame.ca));
    offset += sizeof(c_dlt698_frame.ca);
    //帧头校验 跳过
    hcs_offset = offset;
    offset += sizeof(uint16_t);
    //apdu
    if(1 == c_dlt698_frame.c.control_code.sc){
        for(int i = 0; i < buf_len; i++){
            frame[offset] = buf[i]+c_dlt698_frame.sbc;
            offset++;
        }
    }else{
        memcpy(frame+offset, buf, buf_len);
        offset += buf_len;
    }
    //长度 需要加上尾部校验码的长度
    decltype(c_dlt698_frame.l) ll = offset-cs_start+sizeof(uint16_t);
    memcpy(frame+cs_start, &ll, sizeof(c_dlt698_frame.l));
    //帧头校验hcs
    uint16_t cs = get_fcs16(PPPINITFCS16, frame+cs_start, hcs_offset-cs_start);
    memcpy(frame+hcs_offset, &cs, sizeof(uint16_t));
    //帧校验fcs 赋值
    cs = get_fcs16(PPPINITFCS16, frame+cs_start, offset-cs_start);
    memcpy(frame+offset, &cs, sizeof(uint16_t));
    offset += sizeof(uint16_t);
    //结束符
    memcpy(frame+offset, &c_dlt698_frame.em, sizeof(c_dlt698_frame.em));
    offset += sizeof(c_dlt698_frame.em);
    
    return offset;
}